package ui

import (
	"fmt"
	"strings"
	"io/ioutil"
	"encoding/xml"
	"path/filepath"
	"kumachan/standalone/qt"
)


type NativeObjectGroup struct {
	Definition  *NativeObjectGroupDef
	Widgets     map[string] qt.Widget
	Actions     map[string] qt.Action
}
func CreateNativeObjectGroup(path string) (*NativeObjectGroup, error) {
	var group_def, err1 = analyzeUiXml(path)
	if err1 != nil { return nil, err1 }
	var group, err2 = loadUiXml(group_def)
	if err2 != nil { return nil, err2 }
	return group, nil
}

type NativeObjectGroupDef struct {
	Name     string
	Content  string
	BaseDir  string
	Root     string
	Widgets  map[string] NativeWidgetInfo
	Actions  map[string] struct {}
}
type NativeWidgetInfo struct {
	Class     string
}
func analyzeUiXml(path string) (*NativeObjectGroupDef, error) {
	var ui UiXml
	var content, err1 = ioutil.ReadFile(path)
	if err1 != nil { return nil, err1 }
	var err2 = xml.Unmarshal(content, &ui)
	if err2 != nil { return nil, err2 }
	var widgets = make(map[string] NativeWidgetInfo)
	var root_name = ui.RootWidget.Name
	var root_class = ui.RootWidget.Class
	if !(__IsUiXmlDefaultName(root_name, root_class)) {
		widgets[root_name] = NativeWidgetInfo {
			Class: root_class,
		}
	}
	var actions = make(map[string] struct{})
	for _, item := range ui.RootWidget.Actions {
		actions[item.Name] = struct{}{}
	}
	var add_children func(def UiXmlWidget)
	add_children = func(def UiXmlWidget) {
		var all_children = make([] UiXmlWidget, 0)
		for _, child := range def.Children {
			all_children = append(all_children, child)
		}
		var consume_layout func(UiXmlLayout)
		consume_layout = func(layout UiXmlLayout) {
			for _, item := range layout.Items {
				if item.Widget.Name != "" {
					all_children = append(all_children, item.Widget)
				}
				if item.Layout.Items != nil {
					consume_layout(item.Layout)
				}
			}
		}
		consume_layout(def.Layout)
		for _, child := range all_children {
			var name = child.Name
			var class = child.Class
			if !(__IsUiXmlDefaultName(name, class)) {
				widgets[name] = NativeWidgetInfo {
					Class: class,
				}
			}
			add_children(child)
		}
	}
	add_children(ui.RootWidget)
	var content_string = string(content)
	return &NativeObjectGroupDef {
		Name:    path,
		Content: content_string,
		BaseDir: filepath.Dir(path),
		Root:    root_name,
		Widgets: widgets,
		Actions: actions,
	}, nil
}
func loadUiXml(def *NativeObjectGroupDef) (*NativeObjectGroup, error) {
	var result *NativeObjectGroup
	var err = qt.LoadWidget(string(def.Content), def.BaseDir, func(root qt.Widget) error {
		var widgets = make(map[string] qt.Widget)
		var actions = make(map[string] qt.Action)
		widgets[def.Root] = root
		for name, _ := range def.Widgets {
			var widget, ok = root.FindChildAssumeWidget(name)
			if !(ok) { panic("something went wrong") }
			widgets[name] = widget
		}
		for name, _ := range def.Actions {
			var action, ok = root.FindChildAssumeAction(name)
			if !(ok) { panic("something went wrong") }
			actions[name] = action
		}
		result = &NativeObjectGroup {
			Definition: def,
			Widgets:    widgets,
			Actions:    actions,
		}
		return nil
	})
	if err != nil {
		return nil, fmt.Errorf("bad UI definition '%s' (%w)", def.Name, err)
	}
	return result, nil
}

type UiXml struct {
	RootWidget  UiXmlWidget   `xml:"widget"`
}
type UiXmlWidget struct {
	Name      string           `xml:"name,attr"`
	Class     string           `xml:"class,attr"`
	Children  [] UiXmlWidget   `xml:"widget"`
	Layout    UiXmlLayout      `xml:"layout"`
	Actions   [] UiXmlAction   `xml:"action"`
}
type UiXmlAction struct {
	Name  string   `xml:"name,attr"`
}
type UiXmlLayout struct {
	Items  [] UiXmlLayoutItem   `xml:"item"`
}
type UiXmlLayoutItem struct {
	Widget  UiXmlWidget   `xml:"widget"`
	Layout  UiXmlLayout   `xml:"layout"`
}
var __UiXmlWidgetDefaultNames = map[string] ([] string) {
	"QWidget": { "widget", "centralwidget" },
	"QMainWindow": { "MainWindow" },
	"QWebView": { "webView" },
	"WebView": { "widget", "webView" },
	"QLabel": { "label" },
	"QLineEdit": { "input" },
	"QPlainTextEdit": { "plainTextEdit" },
	"QPushButton": { "button" },
	"QCheckBox": { "checkBox" },
	"QComboBox": { "comboBox" },
	"QListWidget": { "listWidget" },
}
func __IsUiXmlDefaultName(name string, class string) bool {
	var default_names = __UiXmlWidgetDefaultNames[class]
	for _, default_name := range default_names {
		if name == default_name ||
			strings.HasPrefix(name, (default_name + "_")) {
			return true
		}
	}
	return false
}


